﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.EntityClient;
using System.Diagnostics;
using System.Linq;
using System.Web;

namespace ImaginaryDevelopment.AspNet.Utilities
{
    public class SqlConnectionStringManager:System.Data.Entity.Infrastructure.IDbConnectionFactory
    {
        private static string _connectionString;
        //static bool searchedParent=false;
        internal static string EfConnectionString { get; private set; }
        internal static void SetConnectionString(string connectionString, string efConnectionString)
        {
            _connectionString = connectionString;
            EfConnectionString = efConnectionString;
        }
        internal static string ConnectionString
        {
            get
            {
                if (_connectionString.IsNullOrEmpty())
                {
                    _connectionString = FindConnectionString();
                }
                return _connectionString;
            }
            set { _connectionString = value; }
        }
        
        internal static string ConnectionFinderLog { get; private set; }
        static void Log(string value)
        {
            ConnectionFinderLog += value+Environment.NewLine;
        }
        private static string FindConnectionString()
        {
            var connectionStrings = System.Configuration.ConfigurationManager.ConnectionStrings.Cast<ConnectionStringSettings>().ToArray();
            var filesSearched = new string[] { };
            var csFound = new string[] { };
            //if(searchedParent==false)
            {
                var appRoot=System.Web.Hosting.HostingEnvironment.MapPath("~");
                Log("~=" + appRoot);

                System.IO.DirectoryInfo parent;
                
                if (appRoot.EndsWith(System.IO.Path.DirectorySeparatorChar.ToString()))
                    parent=System.IO.Directory.GetParent(appRoot.Substring(0,appRoot.Length-1));
                else
                parent=System.IO.Directory.GetParent(appRoot);
                Log("parent=" + parent);
                var files=System.IO.Directory.GetFiles(parent.FullName,"*.config");
                filesSearched = filesSearched.Concat(files).ToArray();
                if(filesSearched.Any())
                Log("FilesSearched:" + filesSearched.Aggregate((s1, s2) => s1 + "," + s2));

                foreach(var config in files)
                {

                    ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
                    fileMap.ExeConfigFilename = config;
                    try
                    {
                        var c = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
                        foreach (var cs in c.ConnectionStrings.ConnectionStrings.Cast<ConnectionStringSettings>())//.Where(css=>ConfigurationManager.ConnectionStrings[css.Name]==null))
                        {
                            csFound = csFound.Concat(new[] { cs.Name }).ToArray();
                            if (connectionStrings.Any(csn => csn.Name == cs.Name))
                                continue;
                            //ConfigurationManager.ConnectionStrings.Add(cs); //read only error http://david.gardiner.net.au/2008/09/programmatically-setting.html
                            connectionStrings = connectionStrings.Concat(new[] { cs }).ToArray();
                        }
                    }
                    catch (ConfigurationException) //cex)
                    {
                        
                        //throw;
                    }
                    
                }
            }


            if (_connectionString.IsNullOrEmpty())
                using (var cnSql = new System.Data.SqlClient.SqlConnection())
                {
                    for (int i = 0; i < connectionStrings.Count(); i++)
                    {
                        if (connectionStrings[i].Name.ToUpper() != "jaxdug".ToUpper())
                            continue;
                        if (connectionStrings[i].ConnectionString.Contains("metadata="))
                        {
                            var ecsb = new EntityConnectionStringBuilder(connectionStrings[i].ConnectionString);
                            cnSql.ConnectionString = ecsb.ProviderConnectionString;
                        }
                        else if (connectionStrings[i].ConnectionString.Contains("(LocalDb)"))
                        {
                            continue;
                        }
                        else
                            cnSql.ConnectionString = connectionStrings[i].ConnectionString;
                        try
                        {
                            cnSql.Open();
                            cnSql.Close();

                            return connectionStrings[i].ConnectionString;
                        }
                        catch (System.Data.SqlClient.SqlException sqlEx)
                        {
                            Trace.WriteLine("Connection failed:" + sqlEx.ToString());
                        }


                    }
                }
            else {
                throw new InvalidOperationException("_connectionString is null or empty()");
            }
            throw new ApplicationException("Could not find a valid connection string, tried:"+connectionStrings.Count()
                + " "+ connectionStrings.Select(s=>s.Name).Aggregate((s1,s2)=>s1+","+s2)
                +" searched:"+filesSearched.Aggregate((s1,s2)=>s1+","+s2)
                +" csfound:"+csFound.Aggregate((s1,s2)=>s1+","+s2));

        }


        #region IDbConnectionFactory Members

        public System.Data.Common.DbConnection CreateConnection(string nameOrConnectionString)
        {
            var result = new System.Data.SqlClient.SqlConnection(ConnectionString);
            return result;
        }

        #endregion
    }
}